package org.jspar.temp;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.jspar.model.Net;
import org.jspar.model.Terminal;
import org.jspar.tile.Position;
import org.jspar.tile.Tile;

public class Expansion {
	
	private Net net;
	private Terminal terminal;
	private List<Path> pathes = new ArrayList<Path>();
	private List<Expansion> connected = new ArrayList<Expansion>();
	private List<Expansion> netExpansions;
	
	public Expansion(Terminal t, Tile tile, List<Expansion> netExpansions) {
		net = t.net();
		terminal = t;
		addPath(new Path(this, t, tile));
		this.netExpansions = netExpansions;
	}
	
	public void addPath(Path p) {
		pathes.add(p);
		orderPath();
	}
	
	public void removePath(Path p) {
		pathes.remove(p);
	}
	
	public void resetPathCost() {
		for (Path p : pathes) {
			p.resetCost();
		}
		orderPath();
	}

	public void orderPath() {
		Collections.sort(pathes, new Comparator<Path>() {

			@Override
			public int compare(Path o1, Path o2) {
				return o1.cost() - o2.cost();
			}
		});
	}
	
	public List<Expansion> touchingExpansion() {
		List<Expansion> res = new ArrayList<Expansion>();
		Path bestPath = pathes.get(0);
		for (Expansion ex : netExpansions) {
			if (ex != this && ex.contact(bestPath)) {
				res.add(ex);
			}
		}
		return res;
	}

	private boolean contact(Path other) {
		for (Path path : pathes) {
			if (path.contact(other.lastTile())) {
				return true;
			}
		}
		return false;
	}
	
	public void connectTo(Expansion ep) {
		if (! connected.contains(ep))
			connected.add(ep);
		if (! ep.connected.contains(this))
			ep.connected.add(this);
	}

	public Path getBestPath() {
		return pathes.get(0);
	}
	
	public static class ExpansionDistance {

		public Expansion expansion;
		public int distance;

		public ExpansionDistance(Expansion best, int dist) {
			this.expansion = best;
			this.distance = dist;
		}
		
	}
	
	public ExpansionDistance distanceToGo(Position corner) {
		Expansion best = null;
		int dist = -1;
		for (Expansion e : netExpansions) {
			if (e != this && ! connected.contains(e)) {
				int d = corner.manhatanDistance(e.terminal.getGlobalPosition());
				if (best == null || d < dist) {
					best = e;
					dist = d;
				}
			}
		}
		return new ExpansionDistance(best, dist);
	}
	
	public Net net() {
		return net;
	}
	
	public List<Expansion> getConnected() {
		return connected;
	}
	
	@Override
	public String toString() {
		return "Expansion(" + terminal + ")";
	}

}
